package com.piece.mall.service;

import com.piece.core.framework.constant.ExceptionConstants;
import com.piece.core.framework.enums.StatusType;
import com.piece.core.framework.exception.ServerException;
import com.piece.core.framework.support.convert.Convert;
import com.piece.core.framework.util.collection.MapUtil;
import com.piece.core.framework.util.object.BeanUtil;
import com.piece.core.jpa.repository.BaseService;
import com.piece.mall.model.*;
import com.piece.mall.repository.PmsSkuInfoRepository;
import com.piece.mall.repository.PmsSkuSaleAttrValueRepository;
import com.piece.mall.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;

@Slf4j
@Service
@Transactional
public class PmsSkuInfoService extends BaseService<PmsSkuInfo, String> {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Autowired
    private PmsSkuInfoRepository pmsSkuInfoRepository;

    @Resource
    private PmsSkuImagesService pmsSkuImagesService;

    @Resource
    private PmsSkuSaleAttrValueRepository pmsSkuSaleAttrValueRepository;

    @Resource
    private PmsProductAttrValueService pmsProductAttrValueService;

    @Resource
    private SmsSkuFullReductionService smsSkuFullReductionService;

    @Resource
    private PmsAttrService pmsAttrService;

    @Resource
    private PmsAttrGroupService pmsAttrGroupService;

    @Resource
    private WmsWareSkuService wmsWareSkuService;

    @Resource
    private ThreadPoolTaskExecutor taskExecutor;

    @PostConstruct
    public void initRepository() {
        setRepository(pmsSkuInfoRepository);
    }

    public List<PmsSkuInfo> findBySpu(Long spuId) {
        String sql = "select i.*, b.name as brandName, b.logo as brandImg, c.name as catalogName from pms_sku_info i " +
                "left join pms_brand b on b.brand_id = i.brand_id " +
                "left join pms_category c on c.cat_id = i.catalog_id " +
                "where i.spu_id = ?0";
        return pmsSkuInfoRepository.findBySql(sql, new Object[]{ spuId });
    }

    public List<PmsSkuInfo> findByIds(List<Long> skuIds) {
        return pmsSkuInfoRepository.findByCondition(MapUtil.builder(new HashMap<String, Object>())
                .put("Q_skuId_L_IN", skuIds).build(), null);
    }

    /**
     * 保存spu对应的sku信息
     */
    public void saveSkuInfo(PmsSpuInfo spuInfo, List<SkuInfoVo> skuInfos) throws Exception {
        if (!CollectionUtils.isEmpty(skuInfos)) {
            for (SkuInfoVo skuVo : skuInfos) {
                // 1.保存sku基本信息
                String defaultImg = null;
                for (PmsSkuImages skuImage : skuVo.getImages()) {
                    if (StatusType.NORMAL.getCode().equals(skuImage.getDefaultImg())) {
                        defaultImg = skuImage.getImgUrl();
                        break;
                    }
                }
                PmsSkuInfo skuInfo = new PmsSkuInfo();
                BeanUtil.copyProperties(skuVo, skuInfo, "attrs", "skuImages", "descry", "fullCount",
                        "discount", "countStatus", "fullPrice", "reducePrice", "priceStatus", "memberPrice");
                skuInfo.setSpuId(spuInfo.getId());
                skuInfo.setCatalogId(spuInfo.getCatalogId());
                skuInfo.setBrandId(spuInfo.getBrandId());
                skuInfo.setSkuDefaultImg(defaultImg);
                skuInfo.setSaleCount(0L);
                skuInfo = pmsSkuInfoRepository.insert(skuInfo);
                skuVo.setSkuId(skuInfo.getSkuId());

                // 2.保存sku的图片信息
                pmsSkuImagesService.saveSkuImages(skuVo);

                // 3.保存sku的销售属性值
                AtomicLong index = new AtomicLong(0);
                List<PmsSkuSaleAttrValue> saleAttrValues = skuVo.getAttrs().stream().map(attrValue -> {
                    PmsSkuSaleAttrValue skuSaleAttrValue = new PmsSkuSaleAttrValue();
                    skuSaleAttrValue.setSpuId(spuInfo.getId());
                    skuSaleAttrValue.setSkuId(skuVo.getSkuId());
                    skuSaleAttrValue.setAttrId(attrValue.getAttrId());
                    skuSaleAttrValue.setAttrValue(attrValue.getAttrValue());
                    skuSaleAttrValue.setAttrSort(index.incrementAndGet());
                    return skuSaleAttrValue;
                }).collect(Collectors.toList());
                pmsSkuSaleAttrValueRepository.batchInsert(saleAttrValues);

                // 4.保存sku的折扣信息、满减信息、会员价格
                smsSkuFullReductionService.saveSkuReduction(skuVo);
            }
        }
    }

    /**
     * 删除sku信息
     */
    public void deleteSkuInfoBySpuId(Long spuId) {
        List<PmsSkuInfo> skuInfos = findBySpu(spuId);
        List<Long> skuIds = skuInfos.stream().map(skuInfo -> skuInfo.getSkuId()).collect(Collectors.toList());
        deleteSkuInfo(skuIds);
    }

    /**
     * 删除sku信息
     */
    public void deleteSkuInfo(List<Long> skuIds) {
        skuIds.stream().forEach(skuId -> {
            // 1.删除sku基本信息
            pmsSkuInfoRepository.delete(skuId);
            // 2.删除sku的图片信息
            pmsSkuImagesService.deleteSkuImages(skuId);
            // 3.删除sku的销售属性值
            pmsSkuSaleAttrValueRepository.deleteByProperties("skuId", skuId);
            // 4.删除sku的折扣信息、满减信息、会员价格
            smsSkuFullReductionService.deleteSkuReduction(skuId);
        });
    }

    /**
     * 构建购物车数据
     */
    public List<CartItemVo> buildCartItem(List<PmsSkuInfo> skuInfos) {
        List<CartItemVo> carts = new ArrayList<>();
        skuInfos.stream().forEach(skuInfo -> {
            CartItemVo cartItem = new CartItemVo();
            cartItem.setSkuId(skuInfo.getSkuId());
            cartItem.setTitle(skuInfo.getSkuTitle());
            cartItem.setImage(skuInfo.getSkuDefaultImg());
            cartItem.setPrice(skuInfo.getPrice());
            cartItem.setCount(1);
            cartItem.setTotalPrice(skuInfo.getPrice().multiply(BigDecimal.ONE));
            List<PmsSkuSaleAttrValue> saleAttrs =
                    pmsSkuSaleAttrValueRepository.findByCondition("skuId", skuInfo.getSkuId(), null);
            cartItem.setSaleAttrValues(saleAttrs);
            carts.add(cartItem);
        });
        return carts;
    }

    /**
     * 查询商品详情
     */
    public Map getSkuDetail(Long skuId) {
        Map result = new HashMap();
        PmsSkuInfo skuInfo = pmsSkuInfoRepository.findById(skuId);
        if (null == skuInfo) {
            throw new ServerException(ExceptionConstants.NOT_EXIST, "商品-" + skuId);
        }

        ThreadPoolExecutor executor = taskExecutor.getThreadPoolExecutor();
        // 1.封装sku信息
        SkuInfoVo skuInfoVo = new SkuInfoVo();
        skuInfoVo.setSkuId(skuInfo.getSkuId());
        skuInfoVo.setSkuName(skuInfo.getSkuName());
        skuInfoVo.setSkuTitle(skuInfo.getSkuTitle());
        skuInfoVo.setSkuSubtitle(skuInfo.getSkuSubtitle());
        skuInfoVo.setPrice(skuInfo.getPrice());

        // 2.封装sku图片
        CompletableFuture<List<PmsSkuImages>> imagesFuture = CompletableFuture.supplyAsync(() ->
                pmsSkuImagesService.findImagesBySku(skuId), executor);

        // 3.封装产品属性数据
        AttrDataVo attrDataVo = new AttrDataVo();
        Long spuId = skuInfo.getSpuId();
        CompletableFuture<List<SkuSaleAttrVo>> saleAttrsFuture = CompletableFuture.supplyAsync(() -> {
            // 3-1.封装销售属性
            List<Map<String, Object>> saleAttrMap = jdbcTemplate.queryForList("select v.attr_id attr_id, v.attr_name attr_name, v.attr_value attr_value, " +
                    " group_concat(DISTINCT info.sku_id ) sku_ids " +
                    " from pms_sku_info info left join pms_sku_sale_attr_value v " +
                    " on v.sku_id = info.sku_id where info.spu_id = " + spuId +
                    " group by v.attr_id, v.attr_id, v.attr_name, v.attr_value");

            Map<Long, SkuSaleAttrVo> skuSaleAttrMap = new HashMap<>();
            SkuSaleAttrVo tempAttr;
            Long attrId;
            String skuIds;
            SkuSaleAttrVo.AttrValueVo attr_value;
            List<SkuSaleAttrVo.AttrValueVo> tempAttrValues;
            for (Map map : saleAttrMap) {
                attrId = Convert.toLong(map.get("attr_id"), null);
                tempAttrValues = new ArrayList<>();
                tempAttr = skuSaleAttrMap.get(attrId);
                if (null == tempAttr) {
                    tempAttr = new SkuSaleAttrVo();
                    tempAttr.setAttrId(attrId);
                    tempAttr.setAttrName(Convert.toStr(map.get("attr_name")));
                } else {
                    tempAttrValues = tempAttr.getAttrValues();
                }
                skuIds = Convert.toStr(map.get("sku_ids"));
                attr_value = SkuSaleAttrVo.AttrValueVo.builder()
                        .attrValue(Convert.toStr(map.get("attr_value")))
                        .skuIds(skuIds)
                        .build();
                if (skuIds.contains(skuId + "")) {
                    attr_value.setChecked(true);
                    tempAttr.setAttrValue(attr_value.getAttrValue());
                } else {
                    attr_value.setChecked(false);
                }
                tempAttrValues.add(attr_value);
                tempAttr.setAttrValues(tempAttrValues);
                skuSaleAttrMap.put(attrId, tempAttr);
            }

            return skuSaleAttrMap.values().stream().collect(Collectors.toList());
        }, executor);

        CompletableFuture<List<AttrGroupVo>> attrGroupsFuture = CompletableFuture.supplyAsync(() -> {
            // 3-2.封装规格参数
            List<PmsProductAttrValue> baseAttrs = pmsProductAttrValueService.findBySpuId(spuId);
            List<AttrGroupVo> attrGroups = pmsAttrGroupService.getAttrGroupWithAttrs(skuInfo.getCatalogId(), 1);
            attrGroups = attrGroups.stream().map(group -> {
                List<PmsAttr> attrs = group.getAttrs();
                attrs = attrs.stream().filter(baseAttr -> baseAttrs.stream().filter(attr ->
                        attr.getAttrId() == baseAttr.getAttrId()).findAny().isPresent()).map(baseAttr -> {
                    List<PmsProductAttrValue> attrValues = baseAttrs.stream().filter(attrValue -> baseAttr.getAttrId() == attrValue.getAttrId())
                            .collect(Collectors.toList());
                    if (CollectionUtils.isNotEmpty(attrValues)) {
                        PmsProductAttrValue attrValue = attrValues.get(0);
                        baseAttr.setAttrValue(attrValue.getAttrValue());
                    }
                    return baseAttr;
                }).collect(Collectors.toList());
                group.setAttrs(attrs);
                return group;
            }).collect(Collectors.toList());

            return attrGroups;
        }, executor);

        // 4.封装产品库存
        CompletableFuture<Long> stockFuture = CompletableFuture.supplyAsync(() -> wmsWareSkuService.findSkuStock(skuId), executor);

        // 阻塞等待所有任务完成
        CompletableFuture<Void> allFuture = CompletableFuture.allOf(imagesFuture, saleAttrsFuture, attrGroupsFuture, stockFuture);
        try {
            allFuture.get();
            skuInfoVo.setImages(imagesFuture.get());
            skuInfoVo.setStock(stockFuture.get());
            attrDataVo.setSaleAttrs(saleAttrsFuture.get());
            attrDataVo.setAttrGroups(attrGroupsFuture.get());
        } catch (Exception e) {
            log.error("查询sku信息异常：{}", e.getMessage());
        }

        result.put("skuInfo", skuInfoVo);
        result.put("attrData", attrDataVo);
        return result;
    }
}
